#+TITLE:Clarence the Slow Typist
#+AUTHOR:Joshua Branson
# the next line shows all latex previews in latex in the document!  how cool!
#+STARTUP: nolatexpreview
# if I remove the "no" in front of the previous line, then I can show the latex stuff
# also C-c C-x C-l toggles displaying the latax sections as images

Clarence is a slow typist that enters in IP addresses.  Here is a layout of what he has to type:

| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
| . | 0 |   |

Each key is 1 cm apart from each other.

This problem requires you to calculate the distance traveled for each IP address.


- If he types "12", then the distance traveled is 1.
- If he types "17", then the distance traveled is "2"
- If he types "15", then the distance traveled is:

  #+BEGIN_SRC calc
  sqrt (2)
  #+END_SRC

  #+RESULTS:
  : 1.41421356237
- If he types "19", then the distance traveled is:
  a^2 + b^2 = c^2, a = 2, b = 2, c = ?
  \[
  \sqrt{2^{2} + 2^{2}} = c
  \]

  \[
  \sqrt{4 + 4} = c
  \]

  \[
  \sqrt{8} = c
  \]

  #+BEGIN_SRC calc
  sqrt (8)
  #+END_SRC

  #+RESULTS:
  : 2.82842712475

He has to enter in IP address of the form:
[1-9][0-9]{2}\.[0-9]{1-3}\.[0-9]{1-3}
127.999.999.983

I want to calculate the distance traveled whilst typing the whole number.  If he types numbers that are on the same row or
column, then the distance will be a whole number.  I could go ahead and assign them locations like this:

|---+---+---+---+---|
| Y |   |   |   |   |
|---+---+---+---+---|
| 4 | 1 | 2 | 3 |   |
| 3 | 4 | 5 | 6 |   |
| 2 | 7 | 8 | 9 |   |
| 1 | . | 0 |   |   |
|---+---+---+---+---|
| 0 | 1 | 2 | 3 | X |
|---+---+---+---+---|
| Y |   |   |   |   |
|---+---+---+---+---|

So I will store the various locations on the chart below.  10 is ".".
#+BEGIN_SRC emacs-lisp
  (defvar locations '((1 1 4) (2 2 4) (3 3 4)
                      (4 1 3) (5 2 3) (6 3 3)
                      (7 1 2) (8 2 2) (9 3 2)
                      (10 1 1) (0 2 1)))
#+END_SRC

I'll have to make a function that translates "." to the number 10.

#+BEGIN_SRC emacs-lisp
  (defun translate-dot-to-10 (char)
    (when (equal char ".")
      "10" ))
#+END_SRC

You should also know some things about lisp now.  A lisp list looks like this

#+BEGIN_SRC emacs-lisp
'(this is a long list)
#+END_SRC

Internally that list is made up of cons cells.  A cons cell look like this =(X . Y)=, where the X is called the "car" and the Y is called the cdr (pronounced could-er).  A list of cons cells is made like this:
=(X . (Y . Z))= so our previous list can also be written like this:
#+BEGIN_SRC emacs-lisp
  '(this . (is . (a . (long . (list . nil)))))
#+END_SRC

To get the car of a list you just use the =(car)= function like so:

#+BEGIN_SRC emacs-lisp
  (car '(this is a list))
#+END_SRC

To get the cdr of a list, you just use the =(cdr)= function like this:
#+BEGIN_SRC emacs-lisp
(cdr '(this is a list))
#+END_SRC

Now, back to my problem.  I'll create a function that takes in a number from the ip address.  It will spit out a cons cell (X . Y) position of that number.

#+BEGIN_SRC emacs-lisp
  (defun position-cons (number locations) "This will return a cons-cell position of the number"
         ;; if number equals the number in the list
         (if (= number (car (car locations))) ; do-again-test
             ;; then return the cons cell
             (cdr (car locations))
           (position-cons number    ; recursive call
            (cdr locations))))
#+END_SRC

Now I need to make a function that takes two cons cells (aka x and y coordinates) and outputs the distance between them ie:

sqrt ((x_1 - x_2) + (y_1 - y_2))

#+BEGIN_SRC emacs-lisp
  (defun distance-cons (consX consY)
    (let ((x1 (car consX)) (y1 (cdr consX)) (x2 (car consY)) (y2 (cdr consY)))
      (sqrt (+ (* (- x1 x2) (- x1 x2)) (* (- y1 y2) (- y1 y2))))))
#+END_SRC

An example of using distance cons is:

#+BEGIN_SRC emacs-lisp :tangle no
(distance-cons '(0 . 0) '(0 . 1))
#+END_SRC

Now let's write a function that takes sees in the inputted IP address matches this regexp
=[0-9]{1-3}\.[0-9]{1-3}\.[0-9]{1-3}\.[0-9]{1-3}=

Doing regexp matching in elisp sucks!!!  I have to use 2 "\\" to use good regexps.
#+BEGIN_SRC emacs-lisp :export none
(require 's)
(s-matches? "^[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}$" "223.23.2.3")
(s-matches? "^[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}$" "223.243.2.543")
(s-matches? "^[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}$" "223.23.52.53")
#+END_SRC

#+BEGIN_SRC emacs-lisp
  (defun is-ip-address? (string)
    (when (s-matches? "^[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}\.[0-9]\\{1,3\\}$" string)
      t))
#+END_SRC


#+BEGIN_SRC emacs-lisp
  (defun distance (ip-address)
    (when (is-ip-address ip-address)
      distance-cons ((car ip-address) ))
    )
#+END_SRC
